#include <mid_caif_transport.h>

#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <sys/time.h>

#ifndef HAVE_ANDROID_OS
#include <caif/caif_socket.h>
#else
#include <caif_socket.h>
#endif
#include <sys/socket.h>

#include <mid.h>
#include <mid_log.h>
#include <mid_error.h>

#ifndef HAVE_ANDROID_OS
#ifndef AF_CAIF
#define AF_CAIF		37
#endif
#ifndef SOL_CAIF
#define SOL_CAIF	278
#endif
#endif

int mid_caif_transport_open(int* fd) {
	struct sockaddr_caif addr;
	struct timeval tout;
	addr.family = AF_CAIF;
	addr.u.at.type = CAIF_ATTYPE_PLAIN;
	tout.tv_sec = 5;
	tout.tv_usec = 0;

	*fd = socket(AF_CAIF, SOCK_SEQPACKET, CAIFPROTO_AT);
	if (unlikely(*fd == -1)) {
		MLGE("MID: Cannot open caif socket: %s", strerror(errno));
		goto cleanup;
	}

	/* Set the SO_SNDTIMEO to make sure we time out on connect. */
	if (unlikely(setsockopt(*fd, SOL_SOCKET, SO_SNDTIMEO, &tout, sizeof(tout)) == -1)) {
		MLGE("MID: Cannot set caif socket timeout: %s", strerror(errno));
		goto cleanup_socket;
	}

	MLGD("AT: <<<>>> Connecting to AT channel...");
	if (unlikely(connect(*fd, (const struct sockaddr *) &addr, sizeof(addr)) == -1)) {
		MLGE("AT: XXXXXX Unable to connect socket for AT channel: %s", strerror(errno));
		goto cleanup_socket;
	}
	MLGD("AT: <<<>>> Connected to AT channel (fd:%d)", *fd);
	return 0;
cleanup_socket:
	close(*fd);
	*fd = -1;
cleanup:
	return -EMIDAT;
}
